package validator

import (
	"fmt"
	"reflect"
	"strconv"
	"strings"
)

type ContianerRange struct {
	contianerType string
	min           *StringBorder
	max           *StringBorder
}

func NewContainerValidator(tagItem string, contianerType string) Validator {
	var fch = tagItem[0]
	var lch = tagItem[len(tagItem)-1]
	content := tagItem[1 : len(tagItem)-1]
	items := strings.Split(content, ":")
	if len(items) == 2 {
		// 有范围标志
		var min *StringBorder
		if items[0] != "" {
			// 有最小值
			val, err := strconv.ParseInt(items[0], 10, 64)
			if err != nil {
				return nil
			}
			min = &StringBorder{Value: int(val), Include: fch == '['}
		}
		var max *StringBorder
		if items[1] != "" {
			// 有最大值
			val, err := strconv.ParseInt(items[1], 10, 64)
			if err != nil {
				return nil
			}
			max = &StringBorder{Value: int(val), Include: lch == ']'}
		}
		return NewContianerRangeValidator(contianerType, min, max)
	}

	return nil

	// return NewRangeValidator(nil, nil, func(v reflect.Value) int {
	// 	return utf8.RuneCountInString(v.String())
	// })
}

func NewContianerRangeValidator(
	contianerType string,
	min *StringBorder,
	max *StringBorder) *ContianerRange {
	return &ContianerRange{
		contianerType: contianerType,
		min:           min,
		max:           max,
	}
}
func (r *ContianerRange) String() string {
	var str string
	if r.min != nil {
		if r.min.Include {
			str = fmt.Sprintf("[%d", r.min.Value)
		} else {
			str = fmt.Sprintf("(%d", r.min.Value)
		}
	} else {
		str = "("
	}
	if r.max != nil {
		if r.max.Include {
			str = fmt.Sprintf("%s:%d]", str, r.max.Value)
		} else {
			str = fmt.Sprintf("%s:%d)", str, r.max.Value)
		}
	} else {
		str = fmt.Sprintf("%s:)", str)
	}
	return str
}

func (r *ContianerRange) IsValidate(field string, data reflect.Value) error {
	val := data.Interface()
	v, ok := val.(int)
	if !ok {
		return fmt.Errorf("[%s] ContianerRange.IsValidate arg[data] must be int", r.contianerType)
	}
	if r.min != nil {
		if r.min.Include {
			if v < r.min.Value {
				return fmt.Errorf("%s [%s]'s item count must great then or equals %d", r.contianerType, field, r.min.Value)
			}
		} else {
			if v <= r.min.Value {
				return fmt.Errorf("%s [%s]'s item count must great then %d", r.contianerType, field, r.min.Value)
			}
		}
	}
	if r.max != nil {
		if r.max.Include {
			if v > r.max.Value {
				return fmt.Errorf("%s [%s]'s item count must less then or equals %d", r.contianerType, field, r.max.Value)
			}
		} else {
			if v >= r.max.Value {
				return fmt.Errorf("%s [%s]'s item count must less then %d", r.contianerType, field, r.max.Value)
			}
		}
	}
	return nil
}
